package langchain4j.hsl.com.utils;

import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import langchain4j.hsl.com.model.entity.Appointment;
import langchain4j.hsl.com.model.entity.DoctorSchedule;
import langchain4j.hsl.com.service.AppointmentService;
import langchain4j.hsl.com.service.DoctorScheduleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by hsl on 2025/4/25.
 */
@Component
public class AppointmentTools {
    @Autowired
    private AppointmentService appointmentService;
    @Autowired
    private DoctorScheduleService doctorScheduleService;

    // 预约挂号
    @Tool(name = "预约挂号", value = "根据参数，先执行工具方法queryDepartment查询是否可预约，并直接给用户回答是否可预约，" +
            "并让用户确认所有预约信息，用户确认后再进行预约。")
    public String appointment(Appointment appointment) {
        // 查询预约记录
        Appointment appointmentDB = appointmentService.getOne(appointment);
        if (appointmentDB != null) {
            return "您已经预约过该科室的" + appointmentDB.getDate() + "号" + appointmentDB.getTime() +
                    "号" + appointmentDB.getDepartment() + "号" + appointmentDB.getDoctorName() + "医生，请勿重复预约！";
        } else {
            // 检查是否有可用号源
            if (!doctorScheduleService.checkAvailability(appointment)) {
                // 如果用户指定了医生但该医生无号源
                if (appointment.getDoctorName() != null && !appointment.getDoctorName().isEmpty()) {
                    return "抱歉，" + appointment.getDoctorName() + "医生在" + appointment.getDate() + " " +
                            appointment.getTime() + "没有可用号源。";
                } else {
                    // 没有指定医生且该科室该时段无号源
                    return "抱歉，" + appointment.getDepartment() + "科室在" + appointment.getDate() + " " +
                            appointment.getTime() + "没有可用号源。";
                }
            }

            // 如果没有指定医生名称，为用户自动分配一个有号源的医生
            if (appointment.getDoctorName() == null || appointment.getDoctorName().isEmpty()) {
                List<DoctorSchedule> availableDoctors = doctorScheduleService.getAvailableDoctors(appointment);
                if (!availableDoctors.isEmpty()) {
                    // 选择第一个可用医生
                    appointment.setDoctorName(availableDoctors.get(0).getDoctorName());
                }
            }

            // 获取医生排班信息
            DoctorSchedule doctorSchedule = doctorScheduleService.getSchedule(appointment);
            if (doctorSchedule == null) {
                return "抱歉，未找到该医生的排班信息，请重新选择。";
            }

            // 设置 id为null,防止大模型出现幻觉
            appointment.setId(null);
            // 预约挂号
            appointmentService.save(appointment);

            // 减少排班表中的可用容量
            doctorScheduleService.decreaseCapacity(doctorSchedule.getId());

            return "预约成功！您预约的科室是" + appointment.getDepartment() + "，医生是" + appointment.getDoctorName() +
                    "医生，预约时间为" + appointment.getDate() + " " + appointment.getTime() + "，请按时就医！";
        }
    }

    @Tool(name = "取消预约挂号", value = "根据参数，查询预约是否存在，如果存在则删除预约记录并返回取 消预约成功，否则返回取消预约失败")
    @Transactional
    public String cancelAppointment(Appointment appointment) {
        Appointment appointmentDB = appointmentService.getOne(appointment);
        if (appointmentDB != null) {
            // 查找对应的医生排班信息
            DoctorSchedule doctorSchedule = doctorScheduleService.getSchedule(appointmentDB);

            // 删除预约记录
            if (appointmentService.removeById(appointmentDB.getId())) {
                // 如果找到了排班信息，增加可用容量
                if (doctorSchedule != null) {
                    doctorScheduleService.increaseCapacity(doctorSchedule.getId());
                }
                return "取消预约成功";
            } else {
                return "取消预约失败";
            }
        }
        // 取消失败
        return "您没有预约记录，请核对预约科室和时间";
    }

    @Tool(name = "查询是否有号源", value = "根据科室名称，日期，时间和医生查询是否有号源，并返回给用户")
    public boolean queryDepartment(
            @P(value = "科室名称") String name, @P(value = "日期") String date,
            @P(value = "时间，可选值：上午、下午") String time,
            @P(value = "医生名称", required = false) String doctorName
    ) {
        System.out.println("查询是否有号源");
        System.out.println("科室名称：" + name);
        System.out.println("日期：" + date);
        System.out.println("时间：" + time);
        System.out.println("医生名称：" + doctorName);

        // 创建临时Appointment对象用于查询
        Appointment appointment = new Appointment();
        appointment.setDepartment(name);
        appointment.setDate(date);
        appointment.setTime(time);
        appointment.setDoctorName(doctorName);

        // 调用服务检查是否有号源
        boolean hasAvailability = doctorScheduleService.checkAvailability(appointment);

        // 如果没有指定医生但有可用号源，可以返回可用医生列表
        if (hasAvailability && (doctorName == null || doctorName.isEmpty())) {
            List<DoctorSchedule> availableDoctors = doctorScheduleService.getAvailableDoctors(appointment);
            if (!availableDoctors.isEmpty()) {
                String doctorNames = availableDoctors.stream()
                        .map(DoctorSchedule::getDoctorName)
                        .collect(Collectors.joining("、"));
                System.out.println("可预约医生：" + doctorNames);
            }
        }

        return hasAvailability;
    }
}
